package org.libcsp.retrofit2.factorybean;

import com.google.gson.Gson;
import com.google.gson.GsonBuilder;
import lombok.extern.slf4j.Slf4j;
import okhttp3.OkHttpClient;
import org.libcsp.retrofit2.annotation.Retrofit2Client;
import org.springframework.beans.factory.FactoryBean;
import org.springframework.context.EnvironmentAware;
import org.springframework.core.env.Environment;
import org.springframework.lang.NonNull;
import retrofit2.Retrofit;
import retrofit2.converter.gson.GsonConverterFactory;

import java.time.Duration;

@SuppressWarnings("unused")
@Slf4j
public class Retrofit2FactoryBean<T> implements FactoryBean<T>, EnvironmentAware {

    private final Class<T> retrofitClass;

    private Environment environment;

    public Retrofit2FactoryBean(Class<T> retrofitClass) {
        this.retrofitClass = retrofitClass;
    }

    @Override
    public T getObject() {
        Retrofit2Client retrofit2Client = retrofitClass.getAnnotation(Retrofit2Client.class);
        Gson gson = new GsonBuilder()
                .setDateFormat("yyyy-MM-dd HH:mm:ss")
                .create();
        String url = environment.resolveRequiredPlaceholders(retrofit2Client.value());
        OkHttpClient okHttpClient = new OkHttpClient().newBuilder()
                .callTimeout(Duration.ofSeconds(60L))
                .connectTimeout(Duration.ofSeconds(60L))
                .readTimeout(Duration.ofSeconds(60L))
                .writeTimeout(Duration.ofSeconds(60L))
                .build();
        Retrofit retrofit = new Retrofit.Builder()
                .client(okHttpClient)
                .baseUrl(url.endsWith("/") ? url : url + "/")
                .addConverterFactory(GsonConverterFactory.create(gson))
                .build();
        return retrofit.create(retrofitClass);
    }

    @Override
    public Class<?> getObjectType() {
        return retrofitClass;
    }

    @Override
    public void setEnvironment(@NonNull Environment environment) {
        this.environment = environment;
    }

    @Override
    public boolean isSingleton() {
        return true;
    }

}
